package org.innovasix.educational.javap.domain.parser;

import java.util.logging.Logger;

import org.innovasix.educational.javap.domain.ClassFile;
import org.innovasix.educational.javap.domain.constantpool.ConstantPoolEntryFactory;
import org.innovasix.educational.javap.domain.constantpool.MethodsEntryFactory;
import org.innovasix.educational.javap.domain.datatypes.cp_info;
import org.innovasix.educational.javap.domain.datatypes.method_info;

public class ClassParser {

	private static final Logger log = Logger.getLogger(ClassParser.class.getName());
	
	public ClassFile parse(ByteQueue byteQueue){
	
		ClassFile cf = new ClassFile();
		
		cf.setMagic(byteQueue.pollFourBytes());
		
		cf.setMinor_version(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		cf.setMajor_version(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		cf.setConstant_pool_count(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		cf.setConstant_pool(buildConstantPoolTable(cf.getConstant_pool_count().getValue(), byteQueue));
		
		cf.setAccess_flags(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		cf.setThis_class(byteQueue.pollTwoBytes("ClassParser.parse"));

		cf.setSuper_class(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		cf.setInterfaces_count(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		cf.setFields_count(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		cf.setMethods_count(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		buildMethodsTable(cf.getMethods_count().getValue(),byteQueue);
		
		cf.setAttributes_count(byteQueue.pollTwoBytes("ClassParser.parse"));
		
		byteQueue.pollTwoBytes("ClassParser.parse");
		return cf;
	}
	
	private cp_info[] buildConstantPoolTable(int constant_pool_count, ByteQueue byteQueue){
		
		cp_info[] constant_pool = new cp_info[constant_pool_count];
		
		int firstValidEntryIndex = 1;
		int lastValidEntryIndex = constant_pool_count - 1;
		
		for(int currentEntryIndex = firstValidEntryIndex; currentEntryIndex <= lastValidEntryIndex; currentEntryIndex++){

			constant_pool[currentEntryIndex] = ConstantPoolEntryFactory.createNextEntry(byteQueue);
			log.info("Constant pool entry #" + currentEntryIndex + " " + constant_pool[currentEntryIndex].toString());
		}
		
		return constant_pool;
	}
	
	private method_info[] buildMethodsTable(int method_info_count, ByteQueue byteQueue){
		
		method_info[] methods = new method_info[method_info_count];
		
		int firstValidEntryIndex = 0;
		int lastValidEntryIndex = method_info_count - 1;
		
		for(int currentEntryIndex = firstValidEntryIndex; currentEntryIndex <= lastValidEntryIndex; currentEntryIndex++){

			methods[currentEntryIndex] = MethodsEntryFactory.createNextEntry(byteQueue);
			log.info("Methods table entry #" + currentEntryIndex + " " + methods[currentEntryIndex].toString());
		}
		
		return null;
		
	}
}
